#!/bin/bash
source /etc/ceph/ceph-cluster.env
OSD_ID=$1
#################
#environment generate
check_value_is_not_null(){
    if [ ! -n "$1" ];then
        echo "the value is null"
        exit 1
    fi
}

gen_osd_id_range(){
    #Node_Number=`hostname -s|awk -F'-' '{print $2}'`
    let tmp_number=1
    check_value_is_not_null $osd_nodes
    check_value_is_not_null $HostName
    check_value_is_not_null $Node_OSDs
    for i in $osd_nodes;do
        echo "i=$i  HostName=$HostName"
        if [ "$HostName"x == "$i"x ];then
            echo "Node_Number=$tmp_number"
            Node_Number=$(($tmp_number))
            OSD_ID_End=$(($Node_Number * $Node_OSDs - 1))
            OSD_ID_Start="$(($OSD_ID_End + 1 - $Node_OSDs))"
            echo "OSD_ID_Start=$OSD_ID_Start"
            break
        else
            tmp_number=$(($tmp_number + 1))
        fi
    done
}

mkdir_osd_mapping(){
    if [ -d /var/lib/ceph/osd-env ];then
        echo "The dirctor /var/lib/ceph/osd-env is already exist!"
    else
        mkdir /var/lib/ceph/osd-env
    fi
}

gen_disk_by_path_map(){
    if [ ! -f /etc/ceph/ceph-osd.map ];then
        echo "Then file ceph-osd.map is not found."
        exit 1
    fi
    gen_osd_id_range
    mkdir_osd_mapping
    #初始化osd id
    check_value_is_not_null "$OSD_ID_Start"
    osd_id="$OSD_ID_Start"
    echo "osd_id=$OSD_ID_Start"
    check_value_is_not_null "$OSD_ID_End"

    #获取$Cluster_Name-osd.map当前节点上缓存盘列表
    Local_Devices=`cat /etc/ceph/ceph-osd.map|egrep -v "^$|^#" |grep -w "$Node_FQDN"`
    check_value_is_not_null "$Local_Devices"
    Local_Cache_Devices_Map=`echo "$Local_Devices"|awk '{print $2}'`
    check_value_is_not_null "$Local_Cache_Devices_Map"
    echo "Local_Cache_Devices_Map $Local_Cache_Devices_Map"
    caches=0
    fusion_disks=0
    for i in $Local_Cache_Devices_Map;do
        if echo $i|grep ':';then
            if [ "$Cache"x == yesx ];then
                caches=$((caches+1))
            elif [ "$fusion_disks"x = 0x ] ;then
                Cache=yes
                caches=$((caches+1))
            else
                echo "cache disk $i is not found!" 
                exit 1
            fi
        else
            if [ "$Cache"x == nox ];then
                fusion_disks=$((fusion_disks+1))
            elif [ "$caches"x == 0x ];then
                Cache=no
                fusion_disks=$((fusion_disks+1))
                Enable_BCache=no
            else
                echo "Discovering cache disk in fusion disk deployment mode. cache disk is $i!"  
                exit 1
            fi
        fi
    done
    if [ "$Cache"x == yesx ];then
        Local_Cache_Devices=`echo "$Local_Cache_Devices_Map"|awk -F':' '{print $1}'|sort -u`
        check_value_is_not_null "$Local_Cache_Devices"
        for OSD_Cache_Device in $Local_Cache_Devices;do
            Cache_Disk_Path="/dev/disk/by-path/`ls -l /dev/disk/by-path/|egrep -w "$OSD_Cache_Device$"|awk '{print $9}'`"
            OSD_Data_Devices=`echo "$Local_Devices"|egrep  "^$Node_FQDN $OSD_Cache_Device:"|awk -F':' '{print $NF}'|tr -s "\r\n" " "`
            data_number=0
            check_value_is_not_null "$Cache_Disk_Path"
            check_value_is_not_null "$OSD_Data_Devices"
            for Data_Disk in $OSD_Data_Devices;do
                data_number=$((data_number + 1))
                Data_Disk_Path="/dev/disk/by-path/`ls -l /dev/disk/by-path/|egrep -w "$Data_Disk$"|awk '{print $9}'`"
                OSD_Values="$OSD_Values \n$Node_FQDN ceph-$osd_id $data_number $Data_Disk_Path $Cache_Disk_Path"
                check_value_is_not_null "$Data_Disk_Path"
                check_value_is_not_null "$OSD_Values"
                echo "$osd_id $OSD_ID_Start $osd_id $OSD_ID_End"
                if [ "$osd_id" -lt "$OSD_ID_Start" -a "$osd_id" -gt "$OSD_ID_End" ];then
                    echo "osd_id:$osd_id is error."
                    exit 1
                fi
                osd_id=$(($osd_id + 1))
            done
        done
    else
        OSD_Data_Devices=`echo "$Local_Devices"|awk '{print $1=null,$0}'|tr -s "\r\n" " "`
        check_value_is_not_null "$OSD_Data_Devices"
        for Data_Disk in $OSD_Data_Devices;do
            data_number=$((data_number + 1))
            Data_Disk_Path="/dev/disk/by-path/`ls -l /dev/disk/by-path/|egrep -w "$Data_Disk$"|awk '{print $9}'`"
            OSD_Values="$OSD_Values \n$Node_FQDN ceph-$osd_id $data_number $Data_Disk_Path"
            if [ "$osd_id" -lt "$OSD_ID_Start" -a "$osd_id" -gt "$OSD_ID_End" ];then
                echo "osd_id:$osd_id is error."
            fi
            osd_id=$(($osd_id + 1))
        done
    fi
    echo -e "$OSD_Values" > /etc/ceph/ceph-osd-disk-path.map
}

disk_path_map_file_check(){
    if [ -f /etc/ceph/ceph-osd-disk-path.map ];then
        echo "Than file /etc/ceph/ceph-osd-disk-path.map is already exists."
    else
        if [ "$Deploy_Mode"x == k8sx ];then
            while [ ! -f /etc/ceph/ceph-osd-disk-path.map ];do
                echo "Than file /etc/ceph/ceph-osd-disk-path.map is not found."
                sleep 1s
            done
        else
            gen_disk_by_path_map
        fi
    fi
}

cache_osd_env(){
cat > /var/lib/ceph/osd-env/ceph-osd.$OSD_ID <<- EOF
#!/bin/bash
Cache=yes
Enable_BCache=$Enable_BCache
OSD_ID=$OSD_ID
Ceph_FSID=$Ceph_FSID
Block_WAL_Part_Start_Sector=$Block_WAL_Part_Start_Sector
Block_WAL_Part_End_Sector=$Block_WAL_Part_End_Sector
Block_DB_Part_Start_Sector=$Block_DB_Part_Start_Sector
Block_DB_Part_End_Sector=$Block_DB_Part_End_Sector
Block_BCache_Part_Start_Sector=$Block_BCache_Part_Start_Sector
Block_BCache_Part_End_Sector=$Block_BCache_Part_End_Sector
Data_Disk_Path='$Data_Disk_Path' 
Block_DB_Part_Path='$Block_DB_Part_Path' 
Block_WAL_Part_Path='$Block_WAL_Part_Path' 
Block_BCache_Part_Path='$Block_BCache_Part_Path' 
Cache_Disk_Path='$Cache_Disk_Path' 
Cache_Disk_SCSI_ID='$Cache_Disk_SCSI_ID' 
Data_Disk_SCSI_ID='$Data_Disk_SCSI_ID'
OSD_Status=creating
EOF
}

fusion_osd_env(){
cat > /var/lib/ceph/osd-env/ceph-osd.$OSD_ID <<- EOF
#!/bin/bash
Cache=no
Enable_BCache=no
OSD_ID=$OSD_ID
Ceph_FSID=$Ceph_FSID
Block_DB_Part_Start=$Block_DB_Part_Start
Block_DB_Part_End=$Block_DB_Part_End
Block_WAL_Part_Start=$Block_WAL_Part_Start
Block_WAL_Part_End=$Block_WAL_Part_End
Block_Data_Part_Start=$Block_Data_Part_Start
Block_Data_Part_End=$Block_Data_Part_End
Data_Disk_Path='$Data_Device_Path'
Block_DB_Part_Path='$Block_DB_Part_Path'
Block_WAL_Part_Path='$Block_WAL_Part_Path'
Block_Data_Part_Path='$Block_Data_Part_Path'
Data_Disk_SCSI_ID='$Data_Disk_SCSI_ID'
OSD_Status=creating
EOF
}

Sector_Optimal(){
    Optimal_IO_Size=`cat /sys/block/$Pre_mkpart_Disk/queue/optimal_io_size`
    Minimum_IO_Size=`cat /sys/block/$Pre_mkpart_Disk/queue/minimum_io_size`
    Physical_Block_Size=`cat /sys/block/$Pre_mkpart_Disk/queue/physical_block_size`
    Logical_Block_Size=`cat /sys/block/$Pre_mkpart_Disk/queue/logical_block_size`
    Alignment_Offset=`cat /sys/block/$Pre_mkpart_Disk/alignment_offset`
    check_value_is_not_null "$Pre_mkpart_Disk"
    check_value_is_not_null "$Optimal_IO_Size"
    check_value_is_not_null "$Minimum_IO_Size"
    check_value_is_not_null "$Physical_Block_Size"
    check_value_is_not_null "$Logical_Block_Size"
    check_value_is_not_null "$Alignment_Offset"
    #计算物理扇区是否是逻辑扇区整数倍
    echo "Physical_Block_Size=$Physical_Block_Size Logical_Block_Size=$Logical_Block_Size"
    if expr "$Physical_Block_Size" % "$Logical_Block_Size" ;then
        echo "Physical_Block_Size % Logical_Block_Size is not null!"
        exit 1
    fi
    #计算最优起始扇区号
    if [ "$Optimal_IO_Size"x == 0x ];then
        if [ "$Minimum_IO_Size"x == 0x ];then
            Start_Sector=$((Physical_Block_Size/Logical_Block_Size))
        else
            Start_Sector=$(((Physical_Block_Size+Alignment_Offset)/Logical_Block_Size))
        fi
        Start_Sector=$((Start_Sector*2048))
        check_value_is_not_null "$Start_Sector"
    else
        Start_Sector=$(((Optimal_IO_Size+Alignment_Offset)/Physical_Block_Size))
    fi
    #计算逻辑扇区映射到物理扇区的步长
    Sector_Step_Size=$((Physical_Block_Size/Logical_Block_Size))
    Next_Part_Start_Sector=$Start_Sector
}

Sector_let(){
    Part_Start_Sector=$Next_Part_Start_Sector
    check_value_is_not_null "$Part_Start_Sector"
    check_value_is_not_null "$Part_Size"
    if [ "$Part_Size"x == '100%x' ];then
        Part_End_Sector='100%'
    else
        #计算分区容量，以Byte为单位
        Part_Size_Byte=$((Part_Size * 1024 * 1024 * 1024))
        #通过分区容量求出分区理论扇区数量
        Capacity_End_Sectors=$((Part_Size_Byte / Logical_Block_Size))
        if expr $Capacity_End_Sectors % $Sector_Step_Size ;then
            #Remander_Sectors=$((Capacity_End_Sectors % Sector_Step_Size))
            #Difference_Sectors=$((Sector_Step_Size - Remander_Sectors))
            #Part_End_Sectors=$((Capacity_End_Sectors + Difference_Sectors))
            Part_End_Sector=$((Sector_Step_Size - (Capacity_End_Sectors % Sector_Step_Size) + Capacity_End_Sectors + Part_Start_Sector))
        else
            Part_End_Sector=$((Capacity_End_Sectors + Part_Start_Sector))
        fi
        Next_Part_Start_Sector=$((Part_End_Sector + 1))
    fi
}

gen_osd_env() {
    disk_path_map_file_check
    Local_OSD_Values=`cat /etc/ceph/ceph-osd-disk-path.map|egrep -v "^#|^$"|grep -w "^$Node_FQDN"`
    Cache_Devices=`echo "$Local_OSD_Values"|awk '{print $5}'`
    if echo "$Cache_Devices" |grep '/dev/disk/by-path/pci-';then
        Cache=yes
    else
        Cache=no
    fi
    if [ "$Cache"x == nox ];then
        #Fusion Deployment Model Based on All-Flash or All-HDD
        OSD_Fusion_Devices=`echo "$Local_OSD_Values"|awk '{print $4}'`
        Fusion_Device_Values=`echo "$Local_OSD_Values"|grep -w "ceph-$OSD_ID"`
        Data_Disk_Path=`echo "$Fusion_Device_Values"|awk '{print $4}'`
        Data_Disk=`ls -l $Data_Disk_Path|awk -F'/' '{print $NF}'`
        Fusion_Disk_Number=`echo "$Fusion_Device_Values"|awk '{print $3}'`

        Pre_mkpart_Disk=$Data_Disk
        Sector_Optimal
        
	Part_Number=0

        Part_Size="$Block_DB_Size"
        Sector_let
        Part_Number=$((Part_Number + 1))
        Block_DB_Part_Path=$Data_Disk_Path-part$Part_Number
        Block_DB_Part="$Data_Disk$Part_Number"
        Block_DB_Part_Start_Sector="$Part_Start_Sector"
        Block_DB_Part_End_Sector="$Part_End_Sector"

        Part_Size="$Block_WAL_Size"
        Sector_let
        Part_Number=$((Part_Number + 1))
        Block_WAL_Part_Path=$Data_Disk_Path-part$Part_Number
        Block_WAL_Part="$Data_Disk$Part_Number"
        Block_WAL_Part_Start_Sector="$Part_Start_Sector"
        Block_WAL_Part_End_Sector="$Part_End_Sector"

        Part_Size='100%'
        Sector_let
        Part_Number=$((Part_Number + 1))
        Block_Data_Part_Path=$Data_Disk_Path-part$Part_Number
        Block_Data_Part="$Data_Disk$Part_Number"
        Block_Data_Part_Start_Sector="$Part_Start_Sector"
        Block_Data_Part_End_Sector="$Part_End_Sector"

        #生成osd disk SCSI相关变量
        Data_Disk_SCSI_ID=`ls -l /sys/block/$Data_Disk/device|awk -F'/' '{print $NF}'`
        #将osd映射表重定向至文件
        fusion_osd_env
    elif [ "$Cache"x == yesx ];then
        #Mixed Deployment Model Based on NVMe, SSD, and HDD
        Data_Device_Values=`echo "$Local_OSD_Values"|grep -w "ceph-$OSD_ID"`
        Cache_Disk_Path=`echo $Data_Device_Values|awk '{print $5}'`
        Data_Disk_Path=`echo "$Data_Device_Values"|awk '{print $4}'`
        Data_Disk_Number=`echo $Data_Device_Values|awk '{print $3}'`
        echo "Data_Disk_Number=$Data_Disk_Number"
        #Data_Disks_Path=`echo "$Local_OSD_Values"|grep -w "$Cache_Disk_Path"|awk '{print $4}'`
        Cache_Disk=`ls -l $Cache_Disk_Path|awk -F'/' '{print $NF}'`
        Data_Disk=`ls -l $Data_Disk_Path|awk -F'/' '{print $NF}'`
        
        #
        if [ "$Data_Disk_Number"x == 1x ];then
            Pre_mkpart_Disk=$Cache_Disk
            Sector_Optimal
        else
            Pre_mkpart_Disk=$Cache_Disk
            Sector_Optimal
            for i in {1..$Data_Disk_Number};do
                Part_Size="$Block_DB_Size"
                Sector_let
                Part_Number=$((Part_Number + 1))
                Part_Size="$Block_WAL_Size"
                Sector_let
                Part_Number=$((Part_Number + 1))
                if [ "$Enable_BCache"x == yesx ];then
                    Part_Size="$BCache_Size"
                    Sector_let
                    Part_Number=$((Part_Number + 1))
                fi
            done
        fi          

        Part_Size="$Block_DB_Size"
        Sector_let
        Part_Number=$((Part_Number + 1))
        Block_DB_Part_Path=$Cache_Disk_Path-part$Part_Number
        Block_DB_Part="$Cache_Disk$Part_Number"
        Block_DB_Part_Start_Sector="$Part_Start_Sector"
        Block_DB_Part_End_Sector="$Part_End_Sector"

        Part_Size="$Block_WAL_Size"
        Sector_let
        Part_Number=$((Part_Number + 1))
        Block_WAL_Part_Path=$Cache_Disk_Path-part$Part_Number
        Block_WAL_Part="$Cache_Disk$Part_Number"
        Block_WAL_Part_Start_Sector="$Part_Start_Sector"
        Block_WAL_Part_End_Sector="$Part_End_Sector"

        if [ "$Enable_BCache"x == yesx ];then
            Part_Size="$BCache_Size"
            Sector_let
            Part_Number=$((Part_Number + 1))
            Block_BCache_Part_Path=$Cache_Disk_Path-part$Part_Number
            Block_BCache_Part="$Cache_Disk$Part_Number"
            Block_BCache_Part_Start_Sector="$Part_Start_Sector"
            Block_BCache_Part_End_Sector="$Part_End_Sector"
        fi

        #生成osd disk SCSI相关变量
        Cache_Disk_SCSI_ID=`ls -l /sys/block/$Cache_Disk/device|awk -F'/' '{print $NF}'`
        Data_Disk_SCSI_ID=`ls -l /sys/block/$Data_Disk/device|awk -F'/' '{print $NF}'`

        #将osd映射表重定向至文件
        cache_osd_env
    else
        echo "Error: The value Cache is error!"
        exit 1
    fi
}
#generate environment
########################
gen_osd_env
